// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//  File: avtSphereSliceFilter.C
// ************************************************************************* //

#include <avtSphereSliceFilter.h>

#include <vtkVisItCutter.h>
#include <vtkPolyData.h>
#include <vtkQuadric.h>


// ****************************************************************************
//  Method: avtSphereSliceFilter constructor
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
// ****************************************************************************

avtSphereSliceFilter::avtSphereSliceFilter()
{
    quadric = vtkQuadric::New();
}


// ****************************************************************************
//  Method: avtSphereSliceFilter destructor
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
//  Modifications:
//
// ****************************************************************************

avtSphereSliceFilter::~avtSphereSliceFilter()
{
    if (quadric != NULL)
    {
        quadric->Delete();
        quadric = NULL;
    }
}


// ****************************************************************************
//  Method:  avtSphereSliceFilter::Create
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
// ****************************************************************************

avtFilter *
avtSphereSliceFilter::Create()
{
    return new avtSphereSliceFilter();
}


// ****************************************************************************
//  Method:      avtSphereSliceFilter::SetAtts
//
//  Purpose:
//      Sets the state of the filter based on the attribute object.
//
//  Arguments:
//      a        The attributes to use.
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
// ****************************************************************************

void
avtSphereSliceFilter::SetAtts(const AttributeGroup *a)
{
    atts = *(const SphereSliceAttributes*)a;
    origin[0] = atts.GetOrigin()[0];
    origin[1] = atts.GetOrigin()[1];
    origin[2] = atts.GetOrigin()[2];
    radius    = atts.GetRadius();

    double coeffs[10];

    coeffs[0] = 1.;
    coeffs[1] = 1.;
    coeffs[2] = 1.;
    coeffs[3] = 0.;
    coeffs[4] = 0.;
    coeffs[5] = 0.;
    coeffs[6] = -2. * origin[0];
    coeffs[7] = -2. * origin[1];
    coeffs[8] = -2. * origin[2];
    coeffs[9] = origin[0] * origin[0] + origin[1] * origin[1] +
                origin[2] * origin[2] - radius * radius;
    quadric->SetCoefficients(coeffs);
}


// ****************************************************************************
//  Method: avtSphereSliceFilter::Equivalent
//
//  Purpose:
//      Returns true if creating a new avtSphereSliceFilter with the given
//      parameters would result in an equivalent avtSphereSliceFilter.
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
// ****************************************************************************

bool
avtSphereSliceFilter::Equivalent(const AttributeGroup *a)
{
    return (atts == *(SphereSliceAttributes*)a);
}


// ****************************************************************************
//  Method: avtSphereSliceFilter::ExecuteData
//
//  Purpose:
//      Sends the specified input and output through the SphereSlice filter.
//
//  Arguments:
//      in_dr      The input data representation.
//
//  Returns:       The output data representation.
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
//  Modifications:
//
//    Hank Childs, Tue Sep 10 18:25:27 PDT 2002
//    Made all memory management internal to this routine.
//
//    Kathleen Bonnell, Thu Apr 28 10:28:22 PDT 2005
//    Use vtkVisItCutter instead of vtkCutter since it has logic to handle
//    CellData correctly. 
//
//    Eric Brugger, Thu Aug 14 16:42:47 PDT 2014
//    Modified the class to work with avtDataRepresentation.
//
//    Eric Brugger, Tue Aug 25 10:17:57 PDT 2015
//    Modified the routine to return NULL if the output data set had no
//    geometry.
//
// ****************************************************************************

avtDataRepresentation *
avtSphereSliceFilter::ExecuteData(avtDataRepresentation *in_dr)
{
    //
    // Get the VTK data set.
    //
    vtkDataSet *in_ds = in_dr->GetDataVTK();

    vtkVisItCutter *cutter = vtkVisItCutter::New();
    cutter->SetCutFunction(quadric);
    cutter->SetInputData(in_ds);
    cutter->Update();

    vtkDataSet *out_ds = cutter->GetOutput();

    avtDataRepresentation *out_dr = NULL;
    if (out_ds->GetNumberOfCells() > 0)
    {
        out_dr = new avtDataRepresentation(out_ds,
            in_dr->GetDomain(), in_dr->GetLabel());
    }

    cutter->Delete();

    return out_dr;
}


// ****************************************************************************
//  Method: avtSphereSliceFilter::UpdateDataObjectInfo
//
//  Purpose:
//      Changes to topological dimension of the output to be one less that the
//      input.
//
//  Programmer: brugger -- generated by xml2info
//  Creation:   Thu Mar 21 14:45:33 PST 2002
//
//  Modifications:
//    Kathleen Bonnell, Thu Mar  2 14:26:06 PST 2006 
//    Set ZonesSplit.
//
//    Brad Whitlock, Mon Apr  7 15:55:02 PDT 2014
//    Add filter metadata used in export.
//    Work partially supported by DOE Grant SC0007548.
//
// ****************************************************************************

void
avtSphereSliceFilter::UpdateDataObjectInfo(void)
{
    avtDataAttributes &inAtts      = GetInput()->GetInfo().GetAttributes();
    avtDataAttributes &outAtts     = GetOutput()->GetInfo().GetAttributes();
    avtDataValidity   &outValidity = GetOutput()->GetInfo().GetValidity();

    outAtts.SetTopologicalDimension(inAtts.GetTopologicalDimension()-1);
    outValidity.InvalidateZones();
    outValidity.ZonesSplit();

    char params[200];
    snprintf(params, 200, "origin=%lg,%lg,%lg radius=%lg",
        atts.GetOrigin()[0], atts.GetOrigin()[1], atts.GetOrigin()[2],
        atts.GetRadius());
    GetOutput()->GetInfo().GetAttributes().AddFilterMetaData("SphereSlice", params);
}
